/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.felisberto.serialfwder.serial;

import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.TooManyListenersException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Filipe
 */
public class SerialPortReceiver {
    
    private LinkedList<SerialDataListener> listeners;
    private SerialPort thePort;

    public SerialPortReceiver(CommPortIdentifier thePortID, int baud,
            int timeout) {
        try {
            this.listeners = new LinkedList<SerialDataListener>();


            thePort = (SerialPort) thePortID.open("DarwinSys DataComm", timeout * 1000);

            SerialPort myPort = (SerialPort) thePort;

            // set up the serial port
            myPort.setSerialPortParams(baud, SerialPort.DATABITS_8,
                    SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

        } catch (UnsupportedCommOperationException ex) {
            Logger.getLogger(SerialPortReceiver.class.getName()).log(Level.SEVERE, null, ex);
        } catch (PortInUseException ex) {
            Logger.getLogger(SerialPortReceiver.class.getName()).log(Level.SEVERE, null, ex);
        }


    }

    public void addListener(SerialDataListener newListener) {
        listeners.add(newListener);
    }

    public void stop() {
        thePort.removeEventListener();
    }
    
    /**
     * Connects to the serial port and sets up the event listener.
     */
    public void connect() {
        try {
            final BufferedReader br = new BufferedReader(new InputStreamReader(
                    thePort.getInputStream(),"US-ASCII"));
            // Add listener to print received characters to screen
            thePort.addEventListener(new SerialPortEventListener() {

                @Override
                public void serialEvent(SerialPortEvent ev) {
                    try {
                        String raw = br.readLine();
                        for(SerialDataListener lt : listeners){
                            lt.receive(raw);
                        }
                    } catch (IOException e) {
                        Logger.getLogger(SerialPortReceiver.class.getName()).log(Level.SEVERE, null, e);
                    }
                }
            });
            thePort.notifyOnDataAvailable(true);


        } catch (TooManyListenersException ex) {
            Logger.getLogger(SerialPortReceiver.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(SerialPortReceiver.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
